home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / Renderless / vcdplyer.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  13KB  |  522 lines

  1. //------------------------------------------------------------------------------
  2. // File: vcdplyer.cpp
  3. //
  4. // Desc: DirectShow sample code - VMR-based Renderless video player
  5. //
  6. // Copyright (c) 1994-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <mmreg.h>
  11. #include <commctrl.h>
  12. #include <atlbase.h>
  13.  
  14. #include "project.h"
  15.  
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18.  
  19. #define MY_USER_ID 0x1234ACDE
  20.  
  21. /******************************Public*Routine******************************\
  22. * CMpegMovie
  23. *
  24. * Constructors and destructors
  25. *
  26. \**************************************************************************/
  27. CMpegMovie::CMpegMovie(HWND hwndApplication)
  28.     : CUnknown(NAME("Allocator Presenter"), NULL),
  29.       m_hwndApp(hwndApplication),
  30.       m_MediaEvent(NULL),
  31.       m_Mode(MOVIE_NOTOPENED),
  32.       m_Fg(NULL),
  33.       m_Gb(NULL),
  34.       m_Mc(NULL),
  35.       m_Ms(NULL),
  36.       m_Me(NULL),
  37.       m_lpDefSAN(NULL),
  38.       m_bFullScreen(FALSE),
  39.       m_bFullScreenPoss(FALSE),
  40.       m_pddsRenderT(NULL),
  41.       m_pddsPriText(NULL),
  42.       m_pddsPrimary(NULL),
  43.       m_iDuration(-1),
  44.       m_TimeFormat(TIME_FORMAT_MEDIA_TIME)
  45. {
  46.     AddRef();
  47. }
  48.  
  49. CMpegMovie::~CMpegMovie()
  50. {
  51.     ;
  52. }
  53.  
  54. /*****************************Private*Routine******************************\
  55. * SetRenderingMode
  56. *
  57. \**************************************************************************/
  58. HRESULT
  59. SetRenderingMode(
  60.     IBaseFilter* pBaseFilter,
  61.     VMRMode mode
  62.     )
  63. {
  64.     IVMRFilterConfig* pConfig;
  65.     HRESULT hr = pBaseFilter->QueryInterface(IID_IVMRFilterConfig,
  66.         (LPVOID *)&pConfig);
  67.     if(SUCCEEDED(hr))
  68.     {
  69.         pConfig->SetRenderingMode(mode);
  70.         pConfig->Release();
  71.     }
  72.     return hr;
  73. }
  74.  
  75.  
  76. /*****************************Private*Routine******************************\
  77. * AddVideoMixingRendererToFG()
  78. *
  79. \**************************************************************************/
  80. HRESULT
  81. CMpegMovie::AddVideoMixingRendererToFG()
  82. {
  83.     IBaseFilter* pBF = NULL;
  84.     HRESULT hRes = S_OK;
  85.  
  86.     __try {
  87.         CHECK_HR(hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
  88.                                 NULL, CLSCTX_INPROC,IID_IBaseFilter,
  89.                                 (LPVOID *)&pBF));
  90.  
  91.         CHECK_HR(hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer"));
  92.         CHECK_HR(hRes = SetRenderingMode(pBF, VMRMode_Renderless));
  93.  
  94.         CHECK_HR(hRes = pBF->QueryInterface(IID_IVMRSurfaceAllocatorNotify,
  95.             (LPVOID *)&m_lpDefSAN));
  96.  
  97.         CHECK_HR(hRes = CreateDefaultAllocatorPresenter());
  98.         CHECK_HR(hRes = m_lpDefSAN->AdviseSurfaceAllocator(MY_USER_ID, this));
  99.         }
  100.     __finally {
  101.         RELEASE(pBF);
  102.         }
  103.  
  104.     return hRes;
  105. }
  106.  
  107.  
  108. /******************************Public*Routine******************************\
  109. * OpenMovie
  110. *
  111. \**************************************************************************/
  112. HRESULT
  113. CMpegMovie::OpenMovie(
  114.     TCHAR *lpFileName
  115.     )
  116. {
  117.     USES_CONVERSION;
  118.     HRESULT         hres = S_OK;
  119.     IUnknown        *pUnk = NULL;
  120.     WCHAR           FileName[MAX_PATH];
  121.  
  122.     wcscpy(FileName, T2W(lpFileName));
  123.  
  124.     __try
  125.     {
  126.         CHECK_HR(hres = CoCreateInstance(CLSID_FilterGraph,
  127.                                          NULL, CLSCTX_INPROC,
  128.                                          IID_IUnknown, (LPVOID *)&pUnk));
  129.  
  130.         m_Mode = MOVIE_OPENED;
  131.         CHECK_HR(hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg));
  132.         CHECK_HR(hres = AddVideoMixingRendererToFG());
  133.         CHECK_HR(hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb));
  134.         CHECK_HR(hres = m_Gb->RenderFile(FileName, NULL));
  135.         CHECK_HR(hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc));
  136.  
  137.         //
  138.         // Not being able to get the IMediaEvent interface does
  139.         // necessarly mean that we can't play the graph.
  140.         //
  141.         pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
  142.         GetMovieEventHandle();
  143.         pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
  144.     }
  145.     __finally
  146.     {
  147.         if(FAILED(hres))
  148.         {
  149.             RELEASE(m_Ms);
  150.             RELEASE(m_Me);
  151.             RELEASE(m_Mc);
  152.             RELEASE(m_Gb);
  153.             RELEASE(m_Fg);
  154.         }
  155.  
  156.         RELEASE(pUnk);
  157.     }
  158.  
  159.     return hres;
  160. }
  161.  
  162.  
  163. /******************************Public*Routine******************************\
  164. * CloseMovie
  165. *
  166. \**************************************************************************/
  167. DWORD
  168. CMpegMovie::CloseMovie(
  169.     )
  170. {
  171.     m_Mode = MOVIE_NOTOPENED;
  172.     m_bFullScreen = FALSE;
  173.  
  174.     RELEASE(m_Mc);
  175.     RELEASE(m_Me);
  176.     RELEASE(m_Ms);
  177.     RELEASE(m_Gb);
  178.     RELEASE(m_Fg);
  179.     RELEASE(m_lpDefWC);
  180.     RELEASE(m_lpDefSA);
  181.     RELEASE(m_lpDefIP);
  182.  
  183.     return 0L;
  184. }
  185.  
  186.  
  187. /******************************Public*Routine******************************\
  188. * RepaintVideo
  189. *
  190. \**************************************************************************/
  191. BOOL
  192. CMpegMovie::RepaintVideo(
  193.     HWND hwnd,
  194.     HDC hdc
  195.     )
  196. {
  197.     BOOL bRet = FALSE;
  198.     if(m_lpDefWC)
  199.     {
  200.         bRet = (m_lpDefWC->RepaintVideo(hwnd, hdc) == S_OK);
  201.     }
  202.     return bRet;
  203. }
  204.  
  205.  
  206. /******************************Public*Routine******************************\
  207. * PutMoviePosition
  208. *
  209. \**************************************************************************/
  210. BOOL
  211. CMpegMovie::PutMoviePosition(
  212.     LONG x,
  213.     LONG y,
  214.     LONG cx,
  215.     LONG cy
  216.     )
  217. {
  218.     RECT rc;
  219.  
  220.     SetRect(&rc, x, y, x + cx, y + cy);
  221.     BOOL bRet = (m_lpDefWC->SetVideoPosition(NULL, &rc) == S_OK);
  222.     return bRet;
  223. }
  224.  
  225.  
  226. /******************************Public*Routine******************************\
  227. * PlayMovie
  228. *
  229. \**************************************************************************/
  230. BOOL
  231. CMpegMovie::PlayMovie(
  232.     )
  233. {
  234.     REFTIME rt;
  235.     REFTIME rtAbs;
  236.     REFTIME rtDur;
  237.  
  238.     rt = GetCurrentPosition();
  239.     rtDur = GetDuration();
  240.  
  241.     //
  242.     // If we are near the end of the movie seek to the start, otherwise
  243.     // stay where we are.
  244.     //
  245.     rtAbs = rt - rtDur;
  246.     if(rtAbs < (REFTIME)0)
  247.     {
  248.         rtAbs = -rtAbs;
  249.     }
  250.  
  251.     if(rtAbs <= (REFTIME)1)
  252.     {
  253.         SeekToPosition((REFTIME)0,FALSE);
  254.     }
  255.  
  256.     //
  257.     // Change mode after setting m_Mode but before starting the graph
  258.     //
  259.     m_Mode = MOVIE_PLAYING;
  260.     m_Mc->Run();
  261.     return TRUE;
  262. }
  263.  
  264.  
  265. /******************************Public*Routine******************************\
  266. * PauseMovie
  267. *
  268. \**************************************************************************/
  269. BOOL
  270. CMpegMovie::PauseMovie(
  271.     )
  272. {
  273.     m_Mode = MOVIE_PAUSED;
  274.     m_Mc->Pause();
  275.     return TRUE;
  276. }
  277.  
  278.  
  279. /******************************Public*Routine******************************\
  280. * GetStateMovie
  281. *
  282. \**************************************************************************/
  283. OAFilterState
  284. CMpegMovie::GetStateMovie(
  285.     )
  286. {
  287.     OAFilterState State;
  288.     m_Mc->GetState(INFINITE,&State);
  289.     return State;
  290. }
  291.  
  292.  
  293. /******************************Public*Routine******************************\
  294. * StopMovie
  295. *
  296. \**************************************************************************/
  297. BOOL
  298. CMpegMovie::StopMovie(
  299.     )
  300. {
  301.     m_Mode = MOVIE_STOPPED;
  302.     m_Mc->Stop();
  303.     return TRUE;
  304. }
  305.  
  306.  
  307. /******************************Public*Routine******************************\
  308. * GetMediaEventHandle
  309. *
  310. * Returns the IMediaEvent event hamdle for the filter graph if the
  311. * filter graph exists.
  312. *
  313. \**************************************************************************/
  314. HANDLE
  315. CMpegMovie::GetMovieEventHandle(
  316.     )
  317. {
  318.     HRESULT     hr;
  319.  
  320.     if(m_Me != NULL)
  321.     {
  322.         if(m_MediaEvent == NULL)
  323.         {
  324.             hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
  325.         }
  326.     }
  327.     else
  328.     {
  329.         m_MediaEvent = NULL;
  330.     }
  331.  
  332.     return m_MediaEvent;
  333. }
  334.  
  335.  
  336. /******************************Public*Routine******************************\
  337. * GetMovieEventCode
  338. *
  339. \**************************************************************************/
  340. long
  341. CMpegMovie::GetMovieEventCode()
  342. {
  343.     HRESULT hr;
  344.     long    lEventCode;
  345.     LONG_PTR    lParam1, lParam2;
  346.  
  347.     if(m_Me != NULL)
  348.     {
  349.         hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  350.         if(SUCCEEDED(hr))
  351.         {
  352.             hr = m_Me->FreeEventParams(lEventCode, lParam1, lParam2);
  353.             return lEventCode;
  354.         }
  355.     }
  356.  
  357.     return 0L;
  358. }
  359.  
  360.  
  361. /******************************Public*Routine******************************\
  362. * GetDuration
  363. *
  364. * Returns the duration of the current movie
  365. *
  366. \**************************************************************************/
  367. REFTIME
  368. CMpegMovie::GetDuration()
  369. {
  370.     HRESULT hr;
  371.     LONGLONG Duration;
  372.  
  373.     // Should we seek using IMediaSelection
  374.  
  375.     if(m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  376.     {
  377.         hr = m_Ms->GetDuration(&Duration);
  378.         if(SUCCEEDED(hr))
  379.         {
  380.             return double(Duration);
  381.         }
  382.     }
  383.     else if(m_Ms != NULL)
  384.     {
  385.         hr = m_Ms->GetDuration(&Duration);
  386.         if(SUCCEEDED(hr))
  387.         {
  388.             return double(Duration) / UNITS;
  389.         }
  390.     }
  391.     return 0;
  392. }
  393.  
  394.  
  395. /******************************Public*Routine******************************\
  396. * GetCurrentPosition
  397. *
  398. * Returns the current movie position
  399. *
  400. \**************************************************************************/
  401. REFTIME
  402. CMpegMovie::GetCurrentPosition()
  403. {
  404.     REFTIME rt = (REFTIME)0;
  405.     HRESULT hr;
  406.     LONGLONG Position;
  407.  
  408.     // Should we return a media position?
  409.  
  410.     if(m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  411.     {
  412.         hr = m_Ms->GetPositions(&Position, NULL);
  413.         if(SUCCEEDED(hr))
  414.         {
  415.             return double(Position);
  416.         }
  417.     }
  418.     else if(m_Ms != NULL)
  419.     {
  420.         hr = m_Ms->GetPositions(&Position, NULL);
  421.         if(SUCCEEDED(hr))
  422.         {
  423.             return double(Position) / UNITS;
  424.         }
  425.     }
  426.     return rt;
  427. }
  428.  
  429.  
  430. /*****************************Private*Routine******************************\
  431. * SeekToPosition
  432. *
  433. \**************************************************************************/
  434. BOOL
  435. CMpegMovie::SeekToPosition(
  436.     REFTIME rt,
  437.     BOOL bFlushData
  438.     )
  439. {
  440.     HRESULT hr=S_OK;
  441.     LONGLONG llTime =
  442.         LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt);
  443.  
  444.     if(m_Ms != NULL)
  445.     {
  446.         FILTER_STATE fs;
  447.  
  448.         m_Mc->GetState(100, (OAFilterState *)&fs);
  449.         hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
  450.  
  451.         // This gets new data through to the renderers
  452.  
  453.         if(fs == State_Stopped && bFlushData)
  454.         {
  455.             m_Mc->Pause();
  456.             hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
  457.             m_Mc->Stop();
  458.         }
  459.  
  460.         if(SUCCEEDED(hr))
  461.         {
  462.             return TRUE;
  463.         }
  464.     }
  465.     return FALSE;
  466. }
  467.  
  468.  
  469. /******************************Public*Routine******************************\
  470. * SetFullScreenMode
  471. *
  472. \**************************************************************************/
  473. void
  474. CMpegMovie::SetFullScreenMode(
  475.     BOOL bMode
  476.     )
  477. {
  478.     if(bMode && m_bFullScreenPoss)
  479.     {
  480.         HRESULT hr = m_pddsPriText->Blt(NULL, m_pddsPrimary,
  481.             NULL, DDBLT_WAIT, NULL);
  482.         if(SUCCEEDED(hr))
  483.         {
  484.             m_iDuration = 30;
  485.         }
  486.     }
  487. }
  488.  
  489.  
  490. BOOL VerifyVMR(void)
  491. {
  492.     HRESULT hres;
  493.  
  494.     // Verify that the VMR exists on this system
  495.     IBaseFilter* pBF = NULL;
  496.     hres = CoCreateInstance(CLSID_VideoMixingRenderer,
  497.         NULL,
  498.         CLSCTX_INPROC,
  499.         IID_IBaseFilter,
  500.         (LPVOID *)&pBF);
  501.     if(SUCCEEDED(hres))
  502.     {
  503.         pBF->Release();
  504.         return TRUE;
  505.     }
  506.     else
  507.     {
  508.         MessageBox(hwndApp, 
  509.             TEXT("This application requires the Video Mixing Renderer, which is present\r\n")
  510.             TEXT("only on Windows XP.\r\n\r\n")
  511.             TEXT("The Video Mixing Renderer (VMR) is also not enabled when viewing a \r\n")
  512.             TEXT("remote Windows XP machine through a Remote Desktop session.\r\n")
  513.             TEXT("You can run VMR-enabled applications only on your local machine.")
  514.             TEXT("\r\n\r\nThis sample will now exit."),
  515.             TEXT("Video Mixing Renderer capabilities are required"), MB_OK);
  516.  
  517.         return FALSE;
  518.     }
  519. }
  520.  
  521.  
  522.